home *** CD-ROM | disk | FTP | other *** search
- Path: news.larc.nasa.gov!amiga-request
- From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
- Subject: v91i136: sregexp.library 11.1 - a library for regular expressions, Part02/02
- Reply-To: "J. Spencer" <bhgs@utcs.utoronto.ca>
- Newsgroups: comp.sources.amiga
- Message-ID: <comp.sources.amiga.v91i136@ab20.larc.nasa.gov>
- References: <comp.sources.amiga.v91i135@ab20.larc.nasa.gov>
- Date: 29 Jul 91 22:50:35 GMT
- Approved: tadguy@uunet.UU.NET (Tad Guy)
- X-Mail-Submissions-To: amiga@uunet.uu.net
- X-Post-Discussions-To: comp.sys.amiga.misc
-
- Submitted-by: "J. Spencer" <bhgs@utcs.utoronto.ca>
- Posting-number: Volume 91, Issue 136
- Archive-name: libraries/sregexp-11.1/part02
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 2)."
- # Contents: spath.c sregexp.c sregexp.doc
- # Wrapped by tadguy@ab20 on Mon Jul 29 18:50:33 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'spath.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'spath.c'\"
- else
- echo shar: Extracting \"'spath.c'\" \(12861 characters\)
- sed "s/^X//" >'spath.c' <<'END_OF_FILE'
- X
- X/**********************************************************************
- X * This is the stuff for matching to a wildcarded path. see the docs *
- X * *
- X * *
- X * Copyright (c) 1991 by Jon Spencer. *
- X * *
- X * Revision history: *
- X * May 10, 1991 First version basically completed *
- X * *
- X **********************************************************************/
- X
- X#include "sregexp.h"
- X
- Xextern struct DosLibrary *DOSBase;
- X
- X#ifdef __DEBUG__
- Xvoid puts(char *);
- Xvoid printf(char *, ...);
- X#endif
- X
- X#define ROOT ((struct RootNode *)DOSBase->dl_Root)
- X#define INFO ((struct DosInfo *)ROOT->rn_Info<<2)
- X#define DEVC(a) ((struct DeviceList *)a<<2)
- X
- Xstruct SpathInfo *
- Xanchorpath(anc,wld)
- Xchar *anc,*wld;
- X/* This is routine sets everything up for matching wildcard paths.
- X It does the expansion of any wildcards in the volume node part
- X of the path, if any where specified, and gets ready to roll. */
- X{
- X struct SpathInfo *spi;
- X struct SpathNode *spn;
- X BPTR lock;
- X register char *q;
- X char *node,*p,c;
- X struct DeviceList *dvc;
- X struct SregExp *pat;
- X
- X
- X if (!(spi = getmem(sizeof(struct SpathInfo)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X NewList((struct List *)spi);
- X
- X for (q = wld; *q != ':' && *q != '/' && *q; q++) ;
- X
- X if (*q == ':') {
- X if (!(node = getmem(q - wld + 1))) {
- X report(MEM_ERROR);
- X freemem(spi,sizeof(struct SpathInfo));
- X return NULL;
- X }
- X for (q = wld, p = node; *q != ':'; )
- X *p++ = *q++;
- X *p = 0;
- X
- X pat = parsesregexp(node);
- X freemem(node,strlen(node)+1);
- X if (!pat) {
- X freemem(spi,sizeof(struct SpathInfo));
- X return NULL;
- X }
- X
- X /* Check if there is no path to parse */
- X if (*(q+1)) {
- X if (!(spi->spi_SregList = parsepath(q+1))) {
- X freesregexp(pat);
- X freemem(spi,sizeof(struct SpathInfo));
- X return NULL;
- X }
- X } else
- X spi->spi_SregList = NULL;
- X
- X if (pat->sre_Type == SRP_NULL) { /* check for paths matching ":..." */
- X
- X if (!(lock = Lock(anc,SHARED_LOCK))) {
- X freesregexp(pat);
- X freespathinfo(spi);
- X return NULL;
- X }
- X if (!(node = getmem(2))) {
- X report(MEM_ERROR);
- X UnLock(lock);
- X freesregexp(pat);
- X freespathinfo(spi);
- X return NULL;
- X }
- X node[0] = ':';
- X node[1] = 0;
- X if (!(spn = makespathnode(lock,node,spi->spi_SregList))) {
- X UnLock(lock);
- X freemem(node,2);
- X freesregexp(pat);
- X freespathinfo(spi);
- X return NULL;
- X }
- X spn->spn_NodeName = node;
- X AddTail((struct List *)spi,(struct Node *)spn);
- X UnLock(lock);
- X } else {
- X for (dvc = DEVC(INFO->di_DevInfo); dvc; dvc = DEVC(dvc->dl_Next)) {
- X p = (char *)dvc->dl_Name<<2;
- X if (matchnsregexp(p+1,pat,FALSE,*p)) {
- X if (!(node = getmem(*p+2))) {
- X report(MEM_ERROR);
- X freesregexp(pat);
- X freespathinfo(spi);
- X return NULL;
- X }
- X for (c = *p++, q = node; c > 0; c--)
- X *q++ = *p++;
- X *q++ = ':';
- X *q = 0;
- X if (dvc->dl_Type == DLT_DEVICE) {
- X lock = Lock(node,SHARED_LOCK); /* ignore non-filesystem devices */
- X if (!lock)
- X continue;
- X UnLock(lock);
- X }
- X if (!(spn = makespathnode(NULL,node,spi->spi_SregList))) {
- X freemem(node,strlen(node)+1);
- X
- X freespathinfo(spi);
- X return NULL;
- X }
- X spn->spn_NodeName = node;
- X AddTail((struct List *)spi,(struct Node *)spn);
- X }
- X }
- X }
- X freesregexp(pat);
- X } else {
- X /* check if there is any path to parse */
- X if (*wld) {
- X if (!(spi->spi_SregList = parsepath(wld))) {
- X freemem(spi,sizeof(struct SpathInfo));
- X return NULL;
- X }
- X } else
- X spi->spi_SregList = NULL;
- X
- X if (!(spn = makespathnode(NULL,anc,spi->spi_SregList)))
- X freespathinfo(spi);
- X AddTail((struct List *)spi,(struct Node *)spn);
- X }
- X return spi;
- X}
- X
- X#undef ROOT
- X#undef INFO
- X#undef DEVC
- X
- Xstruct SregList *
- Xparsepath(wld)
- Xchar *wld;
- X/* This routine takes a wildcarded path and turns it into a singly
- X linked list of SregExp structures, one node for each path element. */
- X{
- X char *q,*p,*cp,c = 1,recurse;
- X struct SregExp *sre;
- X struct SregList *srl,*srr = NULL,*srn;
- X
- X if (!(cp = getmem(strlen(wld)+1))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X strcpy(cp,wld);
- X
- X q = cp;
- X while (*q && c) {
- X if (strncmp(q,".../",4) == 0) {
- X recurse = SRF_RECURSE;
- X q += 4;
- X } else
- X recurse = 0;
- X p = q;
- X while (*q && *q != '/') q++;
- X c = *q;
- X *q = 0;
- X if (!(sre = parsesregexp(p)))
- X goto bad;
- X sre->sre_Flag |= recurse;
- X *q++ = c;
- X if (!srr) {
- X if (!(srl = srr = getmem(sizeof(struct SregList)))) {
- X report(MEM_ERROR);
- X goto bad;
- X }
- X } else {
- X if (!(srl = (srl->srl_next = getmem(sizeof(struct SregList))))) {
- X report(MEM_ERROR);
- X goto bad;
- X }
- X }
- X srl->srl_next = NULL;
- X srl->srl_sreg = sre;
- X }
- X if (c == '/') /* If path ends in a / then just take dirs */
- X srl->srl_sreg->sre_Flag |= SRF_JUSTDIRS;
- X
- X freemem(cp,strlen(cp)+1);
- X return srr;
- X
- Xbad:
- X if (sre)
- X freesregexp(sre);
- X freemem(cp,strlen(cp)+1);
- X
- X srl = srr;
- X while (srl) {
- X if (srl->srl_sreg)
- X freesregexp(srl->srl_sreg);
- X srn = srl->srl_next;
- X freemem(srl,sizeof(struct SregList));
- X srl = srn;
- X }
- X return NULL;
- X}
- X
- Xstruct SpathNode *
- Xmakespathnode(lock,file,sreg)
- XBPTR lock;
- Xchar *file;
- Xstruct SregList *sreg;
- X/* This routine makes a new node to be linked into the list of current
- X directory locks, basically */
- X{
- X struct SpathNode *spn;
- X BPTR cdir;
- X
- X
- X if (!(spn = getmem(sizeof(struct SpathNode)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X if (lock)
- X cdir = CurrentDir(lock);
- X if (!(spn->spn_Lock = Lock(file,SHARED_LOCK))) {
- X freemem(spn,sizeof(struct SpathNode));
- X return NULL;
- X }
- X spn->spn_SregList = sreg;
- X if (!(Examine(spn->spn_Lock,&spn->spn_FIB))) {
- X UnLock(spn->spn_Lock);
- X freemem(spn,sizeof(struct SpathNode));
- X return NULL;
- X }
- X spn->spn_Flags = 0;
- X spn->spn_NodeName = NULL;
- X if (lock)
- X CurrentDir(cdir);
- X
- X return spn;
- X}
- X
- X
- X
- X#define FILENAME (spn->spn_FIB.fib_FileName)
- X#define NEXTPATH (spn->spn_SregList->srl_next)
- X#define THISPATH (spn->spn_SregList)
- X#define LOCK (spn->spn_Lock)
- X#define FIB (spn->spn_FIB)
- X#define SREG (spn->spn_SregList->srl_sreg)
- X#define ISDIR (FIB.fib_DirEntryType > 0)
- X#define ISRECURSE (SREG->sre_Flag & SRF_RECURSE)
- X#define ISDONEONCE (spn->spn_Flags & SPF_DONEONCE)
- X#define ISJUSTDIRS (SREG->sre_Flag & SRF_JUSTDIRS)
- X#define WANTIT (ISDIR ? dirs >= 0 : !ISJUSTDIRS && dirs <= 0)
- X#define SIGBREAKF_ANY (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F)
- X
- Xint
- Xnextfile(spi,buf,len,dirs)
- Xstruct SpathInfo *spi;
- Xchar *buf;
- Xint len,dirs;
- X/* This routine is a mess. It jumps all over the place and is generally
- X hard to follow. The basic idea behind it is to implement recursion,
- X but without using the stack. Basically the linked list of SpathNode
- X structures, anchored in the SpathInfo structure works as our stack
- X for us. "Why not just use the stack?" you ask. Well, unfortunately,
- X we have to return in the middle of the scan, each time a new match
- X is found. This would mean unrolling all of the stack that defines
- X how far through the search we are to get back to the return address.
- X By using the linked list of SpathInfo structures, we can preserve
- X the state of the 'stack' betweem calls. */
- X{
- X struct SpathNode *spn;
- X
- X
- Xtry_again:
- X
- X if (SetSignal(0,0) & SIGBREAKF_ANY)
- X return SPE_SIGBREAK;
- X
- X spn = spi->spi_TailPred;
- X
- X /* check if we're done. */
- X if (!spn->spn_Pred) {
- X report(ERROR_NO_MORE_ENTRIES);
- X return SPE_ALL_DONE;
- X }
- X
- X /* check if we're at the end of the path: used to match just nodes.*/
- X if (!THISPATH) {
- X if (ISDONEONCE)
- X goto pop;
- X
- X spn->spn_Flags |= SPF_DONEONCE;
- X
- X if (dirs >= 0) {
- X return buildpath(spi,buf,len);
- X } else
- X goto pop;
- X }
- X
- X /* check if we set a delayed decend */
- X if (spn->spn_Flags & SPF_DECEND)
- X goto decend;
- X
- X /* check if it matches the null string, ie parent dir */
- X if (SREG->sre_Type == SRP_NULL) {
- X
- X /* Check if its done or there is no parent. */
- X if (ISDONEONCE || !ParentDir(LOCK))
- X goto pop;
- X
- X spn->spn_Flags |= SPF_DONEONCE; /* Mark it as done. */
- X
- X /* mark it as parent match for buildpath */
- X spn->spn_Flags |= SPF_NEXTPARENT;
- X
- X if (!(spn = makespathnode(LOCK,"/",NEXTPATH)))
- X return SPE_ERROR;
- X AddTail((struct List *)spi,(struct Node *)spn);
- X goto try_again;
- X }
- X
- X /* Check if we can do it quickly */
- X if ((SREG->sre_Type == SRP_STRING ||
- X SREG->sre_Type == SRP_ONECHAR) && !ISRECURSE) {
- X BPTR cdir,lock;
- X
- X /* Have we already done it? */
- X if (ISDONEONCE)
- X goto pop;
- X
- X /* Mark it as done. */
- X spn->spn_Flags |= SPF_DONEONCE;
- X
- X cdir = CurrentDir(LOCK);
- X if (SREG->sre_Type == SRP_STRING)
- X lock = Lock(SREG->sre_Data.string,SHARED_LOCK);
- X else {
- X char n[2];
- X
- X n[0] = SREG->sre_Data.onechar;
- X n[1] = 0;
- X lock = Lock(n,SHARED_LOCK);
- X }
- X CurrentDir(cdir);
- X if (!lock)
- X goto pop;
- X if (!Examine(lock,&FIB)) {
- X UnLock(lock);
- X return SPE_ERROR;
- X }
- X UnLock(lock);
- X
- X if (!NEXTPATH) {
- X if (WANTIT)
- X return buildpath(spi,buf,len);
- X else
- X goto pop;
- X }
- X if (ISDIR) {
- X if (!(spn = makespathnode(LOCK,FILENAME,NEXTPATH))) {
- X return SPE_ERROR;
- X }
- X AddTail((struct List *)spi,(struct Node *)spn);
- X goto try_again;
- X }
- X goto pop;
- X }
- X
- X while (ExNext(LOCK,&FIB)) {
- X if (SetSignal(0,0) & SIGBREAKF_ANY)
- X return SPE_SIGBREAK;
- X
- X if (matchsregexp(FILENAME,SREG,FALSE)) {
- X if (ISDIR && ISRECURSE)
- X spn->spn_Flags |= SPF_DECEND;
- X if (!NEXTPATH) {
- X if (WANTIT)
- X return buildpath(spi,buf,len);
- X } else if (ISDIR) {
- X if (!(spn = makespathnode(LOCK,FILENAME,NEXTPATH))) {
- X return SPE_ERROR;
- X }
- X AddTail((struct List *)spi,(struct Node *)spn);
- X goto try_again;
- X }
- X }
- X if (ISDIR && ISRECURSE) {
- Xdecend:
- X spn->spn_Flags &= ~SPF_DECEND;
- X if (!(spn = makespathnode(LOCK,FILENAME,THISPATH))) {
- X return SPE_ERROR;
- X }
- X AddTail((struct List *)spi,(struct Node *)spn);
- X goto try_again;
- X }
- X }
- X
- X if (IoErr() != ERROR_NO_MORE_ENTRIES)
- X return SPE_ERROR;
- X
- Xpop:
- X RemTail((struct List*)spi);
- X freespathnode(spn);
- X goto try_again;
- X}
- X
- X#undef FILENAME
- X#undef NEXTPATH
- X#undef THISPATH
- X#undef LOCK
- X#undef FIB
- X#undef SREG
- X#undef ISDIR
- X#undef ISRECURSE
- X#undef ISDONEONCE
- X#undef ISJUSTDIRS
- X#undef WANTIT
- X
- X
- Xint
- Xbuildpath(spi,buf,len)
- Xstruct SpathInfo *spi;
- Xchar *buf;
- Xint len;
- X/* This routine turns the current 'stack' of SpathNode structures into
- X a file name the AmigaDOS will like. */
- X{
- X struct SpathNode *spn = spi->spi_Head;
- X int i = 0;
- X char *q;
- X
- X if (len < 1)
- X return SPE_BUFF_FULL;
- X
- X if (spn->spn_Succ && spn->spn_NodeName) {
- X while (spn->spn_Succ->spn_Succ && spn->spn_Succ->spn_NodeName) {
- X spn = spn->spn_Succ;
- X }
- X }
- X
- X if (q = spn->spn_NodeName) {
- X while (*q && i < len)
- X buf[i++] = *q++;
- X if (i >= len)
- X return SPE_BUFF_FULL;
- X }
- X while (spn->spn_Succ) {
- X if (spn->spn_Flags & SPF_NEXTPARENT) {
- X buf[i++] = '/';
- X if (i >= len)
- X return SPE_BUFF_FULL;
- X } else {
- X q = spn->spn_FIB.fib_FileName;
- X while (*q && i < len)
- X buf[i++] = *q++;
- X if (i >= len)
- X return SPE_BUFF_FULL;
- X if (spn->spn_Succ->spn_Succ ||
- X spn->spn_SregList->srl_sreg->sre_Flag & SRF_JUSTDIRS) {
- X buf[i++] = '/';
- X if (i >= len)
- X return SPE_BUFF_FULL;
- X }
- X }
- X spn = spn->spn_Succ;
- X }
- X
- X buf[i] = 0;
- X return i;
- X}
- X
- Xvoid
- Xfreespathinfo(spi)
- Xstruct SpathInfo *spi;
- X/* This routine frees all of the resoureces tied up in a SpathInfo
- X structure */
- X{
- X struct SpathNode *spn;
- X struct SregList *srl,*next;
- X
- X while (spn = (struct SpathNode *)RemTail((struct List *)spi))
- X freespathnode(spn);
- X
- X for (srl = spi->spi_SregList; srl; srl = next) {
- X freesregexp(srl->srl_sreg);
- X next = srl->srl_next;
- X freemem(srl,sizeof(struct SregList));
- X }
- X
- X freemem(spi,sizeof(struct SpathInfo));
- X}
- X
- Xvoid
- Xfreespathnode(spn)
- Xstruct SpathNode *spn;
- X/* This routine frees the memory and lock in a SpathNode structure. */
- X{
- X if (spn->spn_NodeName) {
- X freemem(spn->spn_NodeName,strlen(spn->spn_NodeName)+1);
- X }
- X UnLock(spn->spn_Lock);
- X freemem(spn,sizeof(struct SpathNode));
- X}
- X
- X
- X#ifdef __DEBUG__
- X
- X/* This is some debugging stuff, not compiled into the release version. */
- X
- Xvoid
- Xputs(c)
- Xchar *c;
- X{
- X Write(Output(),c,strlen(c));
- X Write(Output(),"\n",1);
- X}
- X
- X#include <stdarg.h>
- X
- Xextern void vsprintf(char *, char *, va_list);
- X
- Xvoid printf(f, ...)
- Xchar *f;
- X{
- X char buff[100];
- X va_list va;
- X
- X va_start(va,f);
- X vsprintf(buff,f,va);
- X va_end(va);
- X Write(Output(),buff,strlen(buff));
- X}
- X
- X#ifdef __MEMCHECK__
- X
- Xvoid *
- Xcheckmem(s,n,l)
- Xint s,l;
- Xchar *n;
- X{
- X void *f;
- X
- X f = AllocMem(s,0);
- X printf("File: %10s Line %4d Getting %5d at %x\n",n,l,s,f);
- X return f;
- X}
- X
- Xvoid
- Xfreecheck(p,s,n,l)
- Xvoid *p;
- Xint s,l;
- Xchar *n;
- X{
- X printf("File: %10s Line %4d Freeing %5d at %x\n",n,l,s,p);
- X FreeMem(p,s);
- X}
- X
- X#endif
- X
- X#endif
- END_OF_FILE
- if test 12861 -ne `wc -c <'spath.c'`; then
- echo shar: \"'spath.c'\" unpacked with wrong size!
- fi
- # end of 'spath.c'
- fi
- if test -f 'sregexp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sregexp.c'\"
- else
- echo shar: Extracting \"'sregexp.c'\" \(16937 characters\)
- sed "s/^X//" >'sregexp.c' <<'END_OF_FILE'
- X
- X/* This is a routine to test if a string matches a regular expression.
- X *
- X *
- X * The regular expression sytax is a slight extension of the regular
- X * AmigaDos wildcard patterns. Apparently 2.0 has added a few new things
- X * (well, at least a not operator) to the game. This may or may not
- X * be consistant with those additions (it's the way they otta done it.)
- X *
- X * Here it is:
- X *
- X * ? matches any one character
- X *
- X * #(pat) matches zero or more occurances of the pattern pat.
- X *
- X * (pat) seperates out a piece of the pattern.
- X *
- X * pat1|pat2 matches to either pat1 or pat2
- X *
- X * ' escapes the special meaning of these symbols.
- X *
- X * % matches the null string.
- X *
- X * EXTENSIONS
- X *
- X * [chars] will match any single character in the set chars,
- X * specified as single characters or ranges seperated
- X * by a -. Ex. [af-i+] would match a, f, g, h, i, and
- X * +. If ~ is the first character in the set then the
- X * set matched is the complement of the set specified.
- X * Ex. [~a-z] would match any one character that is
- X * not a (lower case if case sensitivity is on) letter.
- X * Note that a [~a] is NOT the same as a ~[a]. The former
- X * would match a 'b' but not a 'ab', whereas the latter
- X * would match both.
- X *
- X * ~(pat) will match anything that doesn't match the pattern.
- X * Note: it is illegal to repeat a not. ie #~a is illegal.
- X * (So is #(~(a)) so don't even try it.) You can repeat
- X * something with a not IN it, as long as it can't be
- X * reduced to the form #~(pattern). (A #[~a] is OK.)
- X * However ~#a has the expected effect (matches any
- X * non-null string not composed entirely of a's.)
- X *
- X * * same as #?.
- X *
- X *
- X */
- X
- X#include "sregexp.h"
- X
- Xconst char wilds[] = { /* string of the wildcards, for easy access */
- X CHR_REPEAT,
- X CHR_NOT,
- X CHR_OPENBRACE,
- X CHR_CLOSEBRACE,
- X CHR_OPENSET,
- X CHR_CLOSESET,
- X CHR_ANYCHAR,
- X CHR_NULL,
- X CHR_OR,
- X CHR_ESCAPE,
- X/* CHR_RANGE, <--- special case */
- X CHR_STAR,
- X 0
- X};
- X
- X#ifdef __DEBUG__
- Xextern void puts(char *);
- Xextern void printf(char *, ...);
- X#endif
- X
- X
- Xstruct SregExp *
- Xparsesregexp(expr)
- Xchar *expr;
- X/* This is the entry point into the parsing subroutines. */
- X{
- X return parsesub(&expr,0);
- X}
- X
- Xstatic struct SregExp *
- Xparsesub(p,end)
- Xchar **p,end;
- X/* This routine will parse a sub expression up until the character
- X 'end' is encontered. This is 0 for the whole pattern and ')'
- X for a subpattern */
- X{
- X struct SregList *list,*head=NULL,*orlist,*orhead=NULL;
- X struct SregExp *sreg;
- X int num = 0,ornum = 0;
- X
- X while (**p != end) {
- X if (**p == CHR_OR) { /* deal with stuff like (ab||cd) == (ab|%|cd) */
- X if (!(sreg = makenull()))
- X goto cleanup;
- X } else {
- X if (!(sreg = parseone(p,TRUE))) /* parse one wildcard */
- X goto cleanup;
- X }
- X if (head) { /* if there's already a list, just stick it on */
- X if (!(list = (list->srl_next = getmem(sizeof(struct SregList))))) {
- X report(MEM_ERROR);
- X goto cleanup;
- X }
- X } else { /* otherwise, make a new list */
- X if (!(list = (head = getmem(sizeof(struct SregList))))) {
- X report(MEM_ERROR);
- X goto cleanup;
- X }
- X }
- X list->srl_sreg = sreg;
- X list->srl_next = NULL;
- X num++;
- X if (**p == CHR_OR) { /* deal with an or */
- X if (!(sreg = makesum(head,num)))
- X goto cleanup;
- X if (orhead) { /* either add onto the or list */
- X if (!(orlist = (orlist->srl_next = getmem(sizeof(struct SregList))))) {
- X report(MEM_ERROR);
- X goto cleanup;
- X }
- X } else { /* or make a new or list */
- X if (!(orlist = (orhead = getmem(sizeof(struct SregList))))) {
- X report(MEM_ERROR);
- X goto cleanup;
- X }
- X }
- X orlist->srl_sreg = sreg;
- X orlist->srl_next = NULL;
- X ornum++;
- X (*p)++;
- X head = NULL;
- X num = 0;
- X }
- X }
- X if (head) {
- X if (!(sreg = makesum(head,num)))
- X goto cleanup;
- X } else {
- X if (!(sreg = makenull()))
- X goto cleanup;
- X }
- X head = NULL;
- X if (orhead) { /* if this expression had an or, clean it up */
- X if (!(orlist = (orlist->srl_next = getmem(sizeof(struct SregList))))) {
- X report(MEM_ERROR);
- X freesregexp(sreg);
- X goto cleanup;
- X }
- X orlist->srl_sreg = sreg;
- X orlist->srl_next = NULL;
- X ornum++;
- X if (!(sreg = makeor(orhead,ornum)))
- X goto cleanup;
- X }
- X
- X return sreg; /* sub expression successfully matched. */
- X
- Xcleanup: /* troubles all head here to clean up */
- X
- X list = head;
- X while (list) { /* free all the bits of the current sum */
- X head = list->srl_next;
- X freesregexp(list->srl_sreg);
- X freemem(list,sizeof(struct SregList));
- X list = head;
- X }
- X list = orhead;
- X while (list) { /* and all of the current or parts */
- X head = list->srl_next;
- X freesregexp(list->srl_sreg);
- X freemem(list,sizeof(struct SregList));
- X list = head;
- X }
- X
- X return NULL; /* return the failure */
- X}
- X
- Xstatic struct SregExp *
- Xmakesum(list,num)
- Xstruct SregList *list;
- Xint num;
- X/* This routine takes a linked list of sreg's and joins them together
- X Under the auspices of one big SRP_SUM type sreg */
- X{
- X struct SregList *lnk;
- X struct SregExp *sreg;
- X int i,len=0;
- X char fixed = SRF_FIXLEN;
- X
- X if (num == 0) {
- X report(ILLEGAL_ERR);
- X return NULL;
- X } else if (num == 1) {
- X sreg = list->srl_sreg;
- X freemem(list,sizeof(struct SregList));
- X return sreg;
- X } if (!(sreg = getmem(sizeof(struct SregExp) + num*sizeof(struct SregExp *)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X sreg->sre_Type = SRP_SUM;
- X sreg->sre_Flag = 0;
- X sreg->sre_Data.number = num;
- X for (i = 0; i < num; i++) {
- X len += realen(list->srl_sreg);
- X fixed &= isfixed(list->srl_sreg) ? SRF_FIXLEN : 0;
- X sreg->sre_List[i] = list->srl_sreg;
- X lnk = list->srl_next;
- X freemem(list,sizeof(struct SregList));
- X list = lnk;
- X }
- X sreg->sre_MinLen = len;
- X sreg->sre_Flag |= fixed;
- X return sreg;
- X}
- X
- Xstatic struct SregExp *
- Xmakeor(list,num)
- Xstruct SregList *list;
- Xint num;
- X/* This does basically the same thing as makesum, except it makes
- X an SRP_OR type sreg to join the list and doesn't deal with some
- X special cases */
- X{
- X struct SregList *lnk;
- X struct SregExp *sreg;
- X int i,len;
- X char fixed = SRF_FIXLEN;
- X
- X if (!(sreg = getmem(sizeof(struct SregExp) + num*sizeof(struct SregExp *)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X sreg->sre_Type = SRP_OR;
- X sreg->sre_Flag = 0;
- X sreg->sre_Data.number = num;
- X for (i = 0; i < num; i++) {
- X if (i == 0)
- X len = realen(list->srl_sreg);
- X else if (len != realen(list->srl_sreg)) {
- X fixed = 0;
- X if (len > realen(list->srl_sreg))
- X len = realen(list->srl_sreg);
- X }
- X fixed &= isfixed(list->srl_sreg) ? SRF_FIXLEN : 0;
- X sreg->sre_List[i] = list->srl_sreg;
- X lnk = list->srl_next;
- X freemem(list,sizeof(struct SregList));
- X list = lnk;
- X }
- X sreg->sre_MinLen = len;
- X sreg->sre_Flag |= fixed;
- X return sreg;
- X}
- X
- Xstatic struct SregExp *
- Xparseone(p,cat)
- Xchar **p,cat;
- X/* This routine parses one wildcard character from the string *p,
- X leaving it set up pointing to the begining of the next
- X wildcard. If 'cat' is true then a string of characters will
- X be grouped together as a SRP_STRING type sreg. It may be
- X false because of the scope rules of ~ and #, which only
- X repeat the very next pattern. */
- X{
- X struct SregExp *sreg;
- X
- X switch (**p) {
- X case (CHR_REPEAT) :
- X (*p)++;
- X if (!(sreg = parseone(p,FALSE)))
- X return NULL;
- X if (sreg->sre_Flag & SRF_NOT) {
- X report(ILLEGAL_ERR);
- X freesregexp(sreg);
- X return NULL;
- X }
- X sreg->sre_Flag |= SRF_REPEAT;
- X break;
- X case (CHR_NOT) :
- X (*p)++;
- X if (!(sreg = parseone(p,FALSE)))
- X return NULL;
- X sreg->sre_Flag |= SRF_NOT;
- X break;
- X case (CHR_OPENBRACE) :
- X (*p)++;
- X sreg = parsesub(p,CHR_CLOSEBRACE);
- X (*p)++;
- X break;
- X case (CHR_OPENSET) :
- X (*p)++;
- X if (!(sreg = getmem(sizeof(struct SregExp)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X sreg->sre_Type = SRP_SETCHAR;
- X sreg->sre_Flag = SRF_FIXLEN;
- X sreg->sre_MinLen = 1;
- X if (!(sreg->sre_Data.setchar = makeset(p))) {
- X freemem(sreg,sizeof(sreg));
- X return NULL;
- X }
- X (*p)++;
- X break;
- X case (CHR_ANYCHAR) :
- X (*p)++;
- X if (!(sreg = getmem(sizeof(struct SregExp)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X sreg->sre_Type = SRP_ANYCHAR;
- X sreg->sre_Flag = SRF_FIXLEN;
- X sreg->sre_MinLen = 1;
- X break;
- X case (CHR_STAR) :
- X (*p)++;
- X if (!(sreg = getmem(sizeof(struct SregExp)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X sreg->sre_Type = SRP_ANYCHAR;
- X sreg->sre_Flag = SRF_FIXLEN | SRF_REPEAT;
- X sreg->sre_MinLen = 1;
- X break;
- X case (CHR_NULL) :
- X (*p)++;
- X if (!(sreg = makenull()))
- X return NULL;
- X break;
- X case (CHR_CLOSEBRACE) :
- X case (CHR_CLOSESET) :
- X case (CHR_OR) :
- X case (0) :
- X report(ILLEGAL_ERR);
- X return NULL;
- X default :
- X if (!(sreg = getmem(sizeof(struct SregExp)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X sreg->sre_Flag = SRF_FIXLEN;
- X if (!cat) {
- X sreg->sre_Data.onechar = onechar(p,FALSE);
- X sreg->sre_Type = SRP_ONECHAR;
- X sreg->sre_MinLen = 1;
- X } else {
- X char *q=*p;
- X int len=0;
- X
- X while (onechar(&q,FALSE))
- X len++;
- X sreg->sre_MinLen = len;
- X if (len == 1) {
- X sreg->sre_Data.onechar = onechar(p,FALSE);
- X sreg->sre_Type = SRP_ONECHAR;
- X } else {
- X sreg->sre_Type = SRP_STRING;
- X if (!(q = sreg->sre_Data.string = getmem(len+1))) {
- X report(MEM_ERROR);
- X freemem(sreg,sizeof(sreg));
- X return NULL;
- X }
- X while (*q++ = onechar(p,FALSE)) ;
- X }
- X }
- X }
- X return sreg;
- X}
- X
- Xstatic struct SregExp *
- Xmakenull()
- X/* This routine makes an node matching the null string. */
- X{
- X struct SregExp *sreg;
- X
- X if (!(sreg = getmem(sizeof(struct SregExp)))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X sreg->sre_Type = SRP_NULL;
- X sreg->sre_Flag = SRF_FIXLEN;
- X sreg->sre_MinLen = 0;
- X}
- X
- Xstatic char
- Xonechar(p,minus)
- Xchar **p,minus;
- X/* this routine picks one character off the string *p. It handles
- X escaping the special meaning of the wildcard characters, and
- X returns 0 if we're at the end of the string or the next
- X char is a wildcard. if 'minus' is true, then the '-' is
- X treated as a wildcard, otherwise it isn't */
- X{
- X if (**p == CHR_ESCAPE)
- X (*p)++;
- X else if (strchr(wilds,**p) || (minus && **p == CHR_RANGE))
- X return 0;
- X return *(*p)++;
- X}
- X
- Xstatic char *
- Xmakeset(p)
- Xchar **p;
- X/* this makes a table of match flags from the character specifier
- X that goes in between [ and ]. It handles a leading '~' and
- X leaves *p pointing to the closing brace. Note: This routine
- X checks to make sure the specifier ends in a ] and fails if
- X it doesn't */
- X{
- X char *set,not=FALSE,ok=FALSE,s,e;
- X
- X if (**p == CHR_NOT) {
- X (*p)++;
- X not = TRUE;
- X }
- X if (!(set = getmem(32))) {
- X report(MEM_ERROR);
- X return NULL;
- X }
- X for (s = 0; s < 32; s++)
- X set[s] = 0;
- X while (s = onechar(p,TRUE)) {
- X ok = TRUE;
- X if (**p == CHR_RANGE) {
- X (*p)++;
- X if (!(e = onechar(p,TRUE))) {
- X report(ILLEGAL_ERR);
- X freemem(set,32);
- X return NULL;
- X }
- X for ( ; s <= e; s++)
- X set[s/8] |= 1 << (s % 8);
- X } else
- X set[s/8] |= 1 << (s % 8);
- X }
- X if (!ok || **p != CHR_CLOSESET) {
- X report(ILLEGAL_ERR);
- X freemem(set,32);
- X return NULL;
- X }
- X if (not) {
- X for(s = 0; s < 32; s++)
- X set[s] = ~set[s];
- X }
- X return set;
- X}
- X
- Xvoid
- Xfreesregexp(sreg)
- Xstruct SregExp *sreg;
- X/* this routine frees up a sreg. It correctly handles freeing the
- X subpattern elements in a SRP_SUM or SRP_OR sreg and frees the
- X match table or string from a SRP_SETCHAR or SRP_STRING sreg.
- X This is one of the externally visible routines. */
- X{
- X int add = 0;
- X
- X if (sreg->sre_Type == SRP_SUM || sreg->sre_Type == SRP_OR) {
- X int i;
- X
- X add = sreg->sre_Data.number * sizeof(struct SregExp *);
- X for (i = 0; i < sreg->sre_Data.number; i++)
- X freesregexp(sreg->sre_List[i]);
- X
- X } else if (sreg->sre_Type == SRP_STRING)
- X freemem(sreg->sre_Data.string,strlen(sreg->sre_Data.string)+1);
- X else if (sreg->sre_Type == SRP_SETCHAR)
- X freemem(sreg->sre_Data.setchar,32);
- X freemem(sreg,sizeof(struct SregExp) + add);
- X}
- X
- Xint
- Xmatchsregexp(p,sreg,up)
- Xchar *p;
- Xstruct SregExp *sreg;
- Xint up;
- X/* This is the externally visible stub to the pattern matching part
- X of sreg. 'p' is the string to match to, sreg is the preparsed
- X sreg, and up indicates if the match is case sensitive. */
- X{
- X return matchnsregexp(p,sreg,up,strlen(p));
- X}
- X
- Xint
- Xmatchnsregexp(p,sreg,up,len)
- Xchar *p;
- Xstruct SregExp *sreg;
- Xint up,len;
- X/* This routine will match a sreg to a string of length 'len'. */
- X/* The length, rather than NULL terminated is used to make a
- X lot of things a lot simpler */
- X{
- X int res,i;
- X
- X if (sreg->sre_Flag & SRF_REPEAT) { /* deal with repeaters. */
- X char not,*h;
- X
- X if (len == 0 || sreg->sre_Type == SRP_ANYCHAR) { /* always true */
- X res = TRUE;
- X goto end;
- X }
- X /* check if the lengths match up */
- X if (len < sreg->sre_MinLen || (sreg->sre_Flag & SRF_FIXLEN &&
- X (sreg->sre_MinLen == 0 || len % sreg->sre_MinLen != 0))) {
- X res = FALSE;
- X goto end;
- X }
- X not = sreg->sre_Flag & SRF_NOT;
- X sreg->sre_Flag &= ~(SRF_REPEAT | SRF_NOT);
- X if (sreg->sre_Flag & SRF_FIXLEN) { /* handle fixed lenght matches */
- X h = p;
- X while (h-p < len) {
- X if (!(res = matchnsregexp(h,sreg,up,sreg->sre_MinLen)))
- X goto end;
- X h += sreg->sre_MinLen;
- X }
- X } else { /* and variable length ones */
- X for (i = len; i >= (sreg->sre_MinLen ? sreg->sre_MinLen : 1); i--) {
- X if (res = matchnsregexp(p,sreg,up,i)) {
- X sreg->sre_Flag |= SRF_REPEAT;
- X if (res = matchnsregexp(p+i,sreg,up,len-i))
- X break;
- X sreg->sre_Flag &= ~SRF_REPEAT;
- X }
- X }
- X }
- X sreg->sre_Flag |= SRF_REPEAT | not;
- X goto end;
- X }
- X
- X /* check the lengths first for quick rejection */
- X if (len < sreg->sre_MinLen || (sreg->sre_Flag & SRF_FIXLEN && len != sreg->sre_MinLen)) {
- X res = FALSE;
- X goto end;
- X }
- X
- X switch (sreg->sre_Type) {
- X case (SRP_SUM) :
- X res = matchsum(&(sreg->sre_List[0]),sreg->sre_Data.number,p,len,up);
- X break;
- X case (SRP_ONECHAR) :
- X res = len == 1 && (up ? *p == sreg->sre_Data.onechar :
- X toupper(*p) == toupper(sreg->sre_Data.onechar));
- X break;
- X case (SRP_SETCHAR) :
- X res = len == 1 && matchset(sreg,*p) || (up ? FALSE :
- X (isupper(*p) ? matchset(sreg,tolower(*p)) :
- X matchset(sreg,toupper(*p))));
- X break;
- X case (SRP_ANYCHAR) :
- X res = len == 1;
- X break;
- X case (SRP_STRING) :
- X if (up)
- X res = !strncmp(p,sreg->sre_Data.string,len);
- X else
- X res = !strnicmp(p,sreg->sre_Data.string,len);
- X break;
- X case (SRP_NULL) :
- X res = len == 0;
- X break;
- X case (SRP_OR) :
- X for (i = 0; i < sreg->sre_Data.number; i++)
- X if (res = matchnsregexp(p,sreg->sre_List[i],up,len)) {
- X break;
- X }
- X break;
- X }
- X
- Xend:
- X
- X if (sreg->sre_Flag & SRF_NOT)
- X return !res;
- X else
- X return res;
- X}
- X
- Xstatic int
- Xmatchsum(list,num,p,len,up)
- Xstruct SregExp *list[];
- Xint num,len,up;
- Xchar *p;
- X/* This routine is called by match to match the elements of a sum
- X of sregs. It tries to be as effecient as possible, and keep
- X recursion to a minimum. It will match any fixed length peices
- X at the begining and end first, then match any fixed length
- X peices in the middle to break the string up. Only then does
- X it do the tiresome matches to the non-fixed length peices. */
- X{
- X int i,res,o;
- X
- X while (num && isfixed(list[0])) {
- X if (!(res = matchnsregexp(p,list[0],up,list[0]->sre_MinLen)))
- X return FALSE;
- X p += list[0]->sre_MinLen;
- X len -= list[0]->sre_MinLen;
- X list++;
- X num--;
- X }
- X while (num && isfixed(list[num-1])) {
- X if (!(res = matchnsregexp(p+len-list[num-1]->sre_MinLen,list[num-1],up,
- X list[num-1]->sre_MinLen)))
- X return FALSE;
- X len -= list[num-1]->sre_MinLen;
- X num--;
- X }
- X if (num == 0)
- X return TRUE;
- X
- X o = 0;
- X for (i = 1; i < num-1; i++) {
- X if (isfixed(list[i])) {
- X for ( ; len-o >= list[i]->sre_MinLen; o++) {
- X if (res = matchnsregexp(p+o,list[i],up,list[i]->sre_MinLen)) {
- X if (!(res = matchsum(list,i,p,o,up)))
- X return FALSE;
- X if (!(res = matchsum(list+(i+1),num-i-1,
- X p+o+list[i]->sre_MinLen,len-o-list[i]->sre_MinLen,up)))
- X return FALSE;
- X return TRUE;
- X }
- X }
- X return FALSE;
- X } else
- X o += realen(list[i]);
- X }
- X
- X if (num == 1)
- X return matchnsregexp(p,list[0],up,len);
- X
- X for (o = len; o >= list[0]->sre_MinLen; o--)
- X if (matchnsregexp(p,list[0],up,o) && matchsum(list+1,num-1,p+o,len-o,up))
- X return TRUE;
- X
- X return FALSE;
- X}
- X
- Xint
- Xiswild(p)
- Xchar *p;
- X/* this is a very simple routine, but it is externally visible. Returns
- X true if the string has wildcard characters (unescaped) false if
- X not */
- X{
- X while (onechar(&p,FALSE)) ;
- X return *p != 0;
- X}
- X
- Xvoid
- Xreport(i)
- Xint i;
- X/* This routine now does set the IoErr value to more information.
- X For now it does nothing. */
- X{
- X struct Process *myself;
- X
- X if (myself = (struct Process *)FindTask(0))
- X myself->pr_Result2 = i;
- X}
- END_OF_FILE
- if test 16937 -ne `wc -c <'sregexp.c'`; then
- echo shar: \"'sregexp.c'\" unpacked with wrong size!
- fi
- # end of 'sregexp.c'
- fi
- if test -f 'sregexp.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sregexp.doc'\"
- else
- echo shar: Extracting \"'sregexp.doc'\" \(13775 characters\)
- sed "s/^X//" >'sregexp.doc' <<'END_OF_FILE'
- XTABLE OF CONTENTS
- X
- Xsregexp.library/AnchorPath
- Xsregexp.library/BuildPath
- Xsregexp.library/FreeSpathInfo
- Xsregexp.library/FreeSregExp
- Xsregexp.library/IsWild
- Xsregexp.library/ParseSregExp
- Xsregexp.library/MatchNSregExp
- Xsregexp.library/MatchSregExp
- Xsregexp.library/NextFile
- X
- Xsregexp.library/AnchorPath sregexp.library/AnchorPath
- X
- X NAME
- X AnchorPath -- get set up to match a wildcard path.
- X
- X SYNOPSIS
- X spath = AnchorPath(anc, wld)
- X D0 A0 A1
- X struct SpathInfo *AnchorPath(char *, char *);
- X
- X FUNCTION
- X This is the first step in matching a wildcarded path. This routine
- X will preparse all of the wildcard elements in the path and set
- X everything up for subsequent calls to NextFile.
- X
- X If NULL is returned, then IoErr can be examined to find out more on
- X whatever went wrong.
- X
- X The wildcarded path is made up of (almost, see bug note) any legal
- X AmigaDOS path name, with wildcard expressions in the place of file
- X and directory names. There is one additional syntax: '.../' means
- X recursively search all sub-directories. so:
- X DH0:.../fred
- X would search all of DH0 for a (file or directory or either, see
- X NextFile) named fred.
- X
- X One pretty nifty feature is that wildcards are legal in the volume
- X node part of the path. This will match to any file system device or
- X assigned directory or volume node that the system currently has
- X mounted. So to match all of the hard drive partitions in your system
- X you would use 'DH?:.../fred'. The root of your current device will
- X be matched only if the pattern explicitly matches a null string (ie
- X either just ':' or '%:')
- X
- X INPUTS
- X anc - a null terminated string which is the name of a
- X directory. All paths returned by BuildPath and NextFile
- X will be relative to this directory.
- X
- X wld - the wildcarded path to be matched.
- X
- X RESULTS
- X spath - a pointer to a SpathInfo structure ready for calls to
- X NextFile.
- X
- X NOTES
- X It will be most usual to pass a pointer to a null string for anc,
- X this will make all paths relative to the current working directory.
- X
- X If the wildcarded path ends in a '/' then the search will match only
- X directories, and the '/' will be appended to all paths returned by
- X BuildPath and NextFile. If you specify a path ending in '/' and then
- X ask NextFile to look for only files the search will fail. If the
- X path does not end in a '/' then no '/' will be appended to the path
- X returned, regardless of whether the match is to a file or a
- X directory.
- X
- X BUGS
- X (well, possible bugs actually) If one of the elements of the path
- X explicitly matches a null string (ie. either /%/ or just //) then
- X the routine will match to the parent directory. This works in all of
- X the cases I have tried (and the only important use, which is at the
- X beginning of the path.) I am just not terribly confident with the
- X way it's done, so if funny bugs creep up, look here first.
- X
- X SEE ALSO
- X ParseSregExp, NextFile, BuildPath, FreeSpathInfo
- X
- Xsregexp.library/BuildPath sregexp.library/BuildPath
- X
- X NAME
- X BuildPath -- build the path to the current match to a SpathInfo
- X structure
- X
- X SYNOPSIS
- X len = BuildPath(spi,buff,len)
- X D0 A0 A1 D0
- X int BuildPath(Struct SpathInfo *, char *, int);
- X
- X FUNCTION
- X The path to the current match of the SpathInfo structure is copied
- X into the buffer and null terminated. This will have unpredictable
- X results, possibly including fireworks, if it is called before the
- X first call to NextFile.
- X
- X This routine will mainly be used to try again with a bigger buffer
- X if NextPath failed with SPE_BUFF_FULL.
- X
- X INPUTS
- X spi - The pointer returned by a call to AnchorPath
- X
- X buff - a buffer length len long to copy the path name into.
- X
- X len - the length of the buffer, buff.
- X
- X
- X RESULTS
- X len - exactly the same as returned by NextFile.
- X
- X SEE ALSO
- X NextFile, AnchorPath.
- X
- Xsregexp.library/FreeSpathInfo sregexp.library/FreeSpathInfo
- X
- X NAME
- X FreeSpathInfo -- free up all of the resources locked by calls
- X to AnchorPath and NextFile
- X
- X SYNOPSIS
- X FreeSpathInfo(spi)
- X A0
- X void FreeSpathInfo(struct SpathInfo *);
- X
- X FUNCTION
- X This will free all of the memory and file locks currently wrapped up
- X in the SpathInfo structure. This is the ONLY way you should try to
- X free up these resources.
- X
- X This routine can be called at any point, either immediately after
- X the call to AnchorPath, or after any calls to NextFile or BuildPath.
- X
- X INPUTS
- X spi - A pointer to a SpathInfo structure to be freed.
- X
- X SEE ALSO
- X AnchorPath.
- X
- Xsregexp.library/FreeSregExp sregexp.library/FreeSregExp
- X
- X NAME
- X FreeSregExp -- free up a preparsed wildcard created by ParseSregExp
- X
- X SYNOPSIS
- X FreeSregExp(sreg)
- X A0
- X void FreeSregExp(struct SregExp *);
- X
- X FUNCTION
- X This routine will free all of the resources associated with a
- X preparsed wildcard expression. This is the only legal way to free
- X the object created by ParseSregExp, and you should not try to do it
- X yourself.
- X
- X INPUTS
- X sreg - a pointer to the preparsed wildcard expression returned
- X by ParseSregExp.
- X
- X SEE ALSO
- X ParseSregExp, MatchNSregExp, MatchSregExp.
- X
- Xsregexp.library/IsWild sregexp.library/IsWild
- X
- X NAME
- X IsWild -- test if a string has any unescaped wildcard characters.
- X
- X SYNOPSIS
- X bool = IsWild(wildcard);
- X D0 A0
- X int IsWild(char *);
- X
- X FUNCTION
- X This routine merely checks if the string contains any unescaped
- X wildcard characters. It does not actually test if the string is
- X wild. For example, it would fail on '(this is a test)' because of
- X the round brackets, which are wildcard characters.
- X
- X INPUTS
- X wildcard - a pointer to a wildcard string.
- X
- X RESULTS
- X bool - non-zero if any unescaped wildcard characters were
- X found.
- X
- X NOTES
- X This routine has very little merit, and is not really all that
- X useful. I will probably add a routine in future versions that does
- X the same thing but takes the preparsed wildcard expression and
- X returns the unique string which it will match, or NULL.
- X
- X SEE ALSO
- X ParseSregExp.
- X
- Xsregexp.library/ParseSregExp sregexp.library/ParseSregExp
- X
- X NAME
- X ParseSregExp -- preparse a wildcard expression for matching.
- X
- X SYNOPSIS
- X sreg = ParseSregExp(wildcard)
- X D0 A0
- X struct SregExp *ParseSregExp(char *);
- X
- X FUNCTION
- X A wildcard string must be preparsed before it can be passed to
- X MatchSregExp or MatchNSregExp to actually test if it matches a given
- X target string.
- X
- X This function returns a pointer to the successfully created
- X structure, or NULL on failure. On failure, IoErr() can be examined
- X to get more information on the cause of the trouble.
- X ERROR_INVALID_COMPONENT_NAME is returned if the wildcard string is
- X illegal and ERROR_NO_FREE_STORE is returned if memory allocation
- X failed.
- X
- X WILDCARD SYNTAX
- X The wildcard syntax accepted is an extension of the usual AmigaDOS
- X wildcards. Any 1.3 wildcard expression should be ok. Apparently
- X under 2.0 they have added a not operator, and the one here may or
- X may not be compatible with the way they have done it. (They SHOULD
- X have done it this way.)
- X
- X Here is a synopsis:
- X
- X ? matches any one character
- X
- X #(pat) matches zero or more occurrences of the pattern pat.
- X
- X (pat) separates out a piece of the pattern.
- X
- X pat1|pat2 matches to either pat1 or pat2
- X
- X ' escapes the special meaning of these symbols.
- X
- X % matches the null string.
- X
- X These are the extensions:
- X
- X [chars] will match any single character in the set chars,
- X specified as single characters or ranges separated by a
- X -. Ex. [af-i+] would match a, f, g, h, i, and +. If ~
- X is the first character in the set then the set matched
- X is the complement of the set specified. Ex. [~a-z] would
- X match any one character that is not a (lower case if
- X case sensitivity is on) letter. Note that a [~a] is NOT
- X the same as a ~[a]. The former would match a 'b' but not
- X a 'ab', whereas the latter would match both. Special
- X care should be taken when using this wildcard in case
- X insensitive matches. As expected, [a] would match either
- X 'a' or 'A' in a case insensitive search, but [~a] would
- X match anything, since it doesn't match 'a', but would
- X match a 'A'.
- X
- X ~(pat) will match anything that doesn't match the pattern.
- X Note: it is illegal to repeat a not. ie #~a is illegal.
- X (So is #(~(a)) so don't even try it.) You can repeat
- X something with a not IN it, as long as it can't be
- X reduced to the form #~(pattern). (A #[~a] is OK.)
- X However ~#a has the expected effect (matches any
- X non-null string not composed entirely of a's.)
- X
- X * same as #?.
- X
- X INPUTS
- X wildcard - a pointer to the null terminated wildcard expression
- X string.
- X
- X RETURNS
- X sreg - a preparsed version of the wildcard expression.
- X
- X SEE ALSO
- X FreeSregExp, MatchNSregExp, MatchSregExp.
- X
- Xsregexp.library/MatchNSregExp sregexp.library/MatchNSregExp
- X
- X NAME
- X MatchNSregExp - match a preparsed wildcard expression to a target
- X
- X SYNOPSIS
- X bool = MatchNSregExp(target,sreg,case,len)
- X D0 A0 A1 D0 D1
- X int MatchNSregExp(char *, struct SregExp *, int int);
- X
- X FUNCTION
- X This function tests if the given fixed length target string matches
- X the preparsed wildcard expression.
- X
- X This routine is identical to MatchSregExp, except it takes a pointer
- X to a string and its length, rather than a null terminated string.
- X
- X INPUTS
- X target - the null terminated target string you wish to test
- X against the wildcard expression.
- X
- X sreg - the preparsed wildcard expression.
- X
- X case - if this is non-zero then the match is case sensitive,
- X otherwise it is case insensitive.
- X
- X len - the length of the string pointed to by target.
- X
- X RESULTS
- X bool - non-zero if the target matches the expression, zero
- X otherwise.
- X
- X NOTES
- X See ParseSregExp for a discussion of the wildcard expression and the
- X tricky behaviour of character sets (ie. [...]) when the search is
- X case insensitive.
- X
- X This routine is handy for matching BCPL strings. If p is a c
- X pointer (byte, not longword address) of a BCPL string then
- X
- X MatchNSregExp(p+1,sreg,case,*p)
- X
- X will test the BCPL string for a match.
- X
- X SEE ALSO
- X FreeSregExp, ParseSregExp, MatchSregExp.
- X
- Xsregexp.library/MatchSregExp sregexp.library/MatchSregExp
- X
- X NAME
- X MatchSregExp - match a preparsed wildcard expression to a target
- X
- X SYNOPSIS
- X bool = MatchSregExp(target,sreg,case)
- X D0 A0 A1 D0
- X int MatchSregExp(char *, struct SregExp *, int);
- X
- X FUNCTION
- X This function tests if the given null terminated target string
- X matches the preparsed wildcard expression.
- X
- X This routine is identical to MatchNSregExp, except it takes a
- X pointer to a null terminated string, rather than a string and its
- X length.
- X
- X INPUTS
- X target - the null terminated target string you wish to test
- X against the wildcard expression.
- X
- X sreg - the preparsed wildcard expression.
- X
- X case - if this is non-zero then the match is case sensitive,
- X otherwise it is case insensitive.
- X
- X RESULTS
- X bool - non-zero if the target matches the expression, zero
- X otherwise.
- X
- X NOTES
- X See ParseSregExp for a discussion of the wildcard expression and the
- X tricky behaviour of character sets (ie. [...]) when the search is
- X case insensitive.
- X
- X This call currently just results in the call:
- X
- X MatchNSregExp(target,sreg,case,strlen(target));
- X
- X but this may change in future version.
- X
- X SEE ALSO
- X FreeSregExp, ParseSregExp, MatchNSregExp.
- X
- Xsregexp.library/NextFile sregexp.library/NextFile
- X
- X NAME
- X NextFile -- return the next (or first) file matching the path.
- X
- X SYNOPSIS
- X len = NextFile(spi,buff,len,dirs)
- X D0 A0 A1 D0 D1
- X int NextFile(struct SpathInfo *, char *, int int);
- X
- X FUNCTION
- X This routine copies the path to the next (or first, if this is the
- X first call) file or directory matching the wildcard in the SpathInfo
- X structure created by a call to AnchorPath.
- X
- X The usual calling sequence would be:
- X AnchorPath
- X repeat while no errors and more files
- X NextFile
- X FreeSpathInfo
- X
- X The length of the path is returned, or if there is an error or there
- X are no more matches a negative result is returned. Both the
- X negative number and the Value if IoErr will give more information
- X about why the routine returned.
- X
- X INPUTS
- X spi - The pointer returned by a call to AnchorPath
- X
- X buff - a buffer length len long to copy the path name into.
- X
- X len - the length of the buffer, buff.
- X
- X dirs - if this is greater than zero, only directories will
- X match; if it is zero, both files and directories will
- X match; if it is less than zero, only files will match.
- X See the defines in the include file.
- X
- X RESULTS
- X len - on success this will be the length of the path copied
- X into the buffer. If it is less than zero, some kind of
- X special event is signalled.
- X SPE_ALL_DONE - This signals there are no more matches
- X to the path. IoErr will also be set to
- X ERROR_NO_MORE_ENTRIES
- X SPE_ERROR - Some error happened, see IoErr.
- X SPE_BUFF_FULL - The buffer you suplied was not big
- X enough for the path name. Get a bigger
- X one and call BuildPath.
- X SPE_SIGBREAK - One of the dos break signals was
- X received by your process. This does not
- X clear the signals, but since some
- X searches can take a while it checks
- X every now and again. You can just clear
- X the signal and call NextPath again to
- X ignore the signal.
- X
- X NOTES
- X It is meaningless to mix calls with a different value of dirs.
- X Anything passed by in a call in which you did not ask for objects of
- X a given type will not reappear in subsequent calls in which you do
- X ask for that type.
- X
- X SEE ALSO
- X AnchorPath, BuildPath.
- X
- END_OF_FILE
- if test 13775 -ne `wc -c <'sregexp.doc'`; then
- echo shar: \"'sregexp.doc'\" unpacked with wrong size!
- fi
- # end of 'sregexp.doc'
- fi
- echo shar: End of archive 2 \(of 2\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
- Mail comments to the moderator at <amiga-request@uunet.uu.net>.
- Post requests for sources, and general discussion to comp.sys.amiga.misc.
-